package com.wugh.fast.kernel.core.util;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;

/**
 * 说明: SPEL上下文构造器
 * <pre>
 *      1. 支持常用的rootObject(method,args,target,targetClass) #root.method 或method
 *      2. 支持方法名称(JDK1.8之后) #p0 #a0 #argName
 *      3. 支持ioc容器, @beanName
 *      4. 支持返回值, #result
 * </pre>
 *
 * @author wugh
 * @date 2019-12-09 09:51
 */
public class FastSpelContextBuilder {
    private FastSpelContextBuilder() {
    }

    /**
     * root对象
     */
    private Object rootObject;
    /**
     * 方法
     */
    private Method method;
    /**
     * 参数
     */
    private Object[] arguments;

    private Object target;

    private Class<?> targetClass;

    /**
     * bean的工唱
     */
    private BeanResolver beanResolver;
    /**
     * 返回结果
     */
    private Object result;
    /**
     * 是有有
     */
    private boolean hasResult = false;

    public Method getMethod() {
        return method;
    }

    public Object[] getArgs() {
        return arguments;
    }

    public Object getTarget() {
        return target;
    }

    public Class<?> getTargetClass() {
        return targetClass;
    }

    public FastSpelContextBuilder rootObject(Object rootObject) {
        this.rootObject = rootObject;
        return this;
    }

    public FastSpelContextBuilder method(Method method) {
        this.method = method;
        return this;
    }

    public FastSpelContextBuilder arguments(Object[] arguments) {
        this.arguments = arguments;
        return this;
    }

    public FastSpelContextBuilder target(Object target) {
        this.target = target;
        return this;
    }

    public FastSpelContextBuilder targetClass(Class<?> targetClass) {
        this.targetClass = targetClass;
        return this;
    }

    public FastSpelContextBuilder beanResolver(BeanResolver beanResolver) {
        this.beanResolver = beanResolver;
        return this;
    }

    public FastSpelContextBuilder result(Object result) {
        this.result = result;
        this.hasResult = true;
        return this;
    }

    /**
     * 使用默认的bean工厂,即使用spring的ioc容器作为bean工常
     *
     * @return
     */
    public FastSpelContextBuilder useDefaultBeanResolver() {
        this.beanResolver = new BeanFactoryResolver(SpringContextHolder.getApplicationContext());
        return this;
    }

    public static FastSpelContextBuilder builder() {
        return new FastSpelContextBuilder();
    }

    public EvaluationContext build() {
        StandardEvaluationContext evaluationContext;
        if (method != null) {
            evaluationContext = new MethodBasedEvaluationContext(this, method, arguments, new DefaultParameterNameDiscoverer());
        } else {
            evaluationContext = new StandardEvaluationContext(rootObject);

        }
        if (hasResult) {
            evaluationContext.setVariable("result", this.result);
        }
        if (beanResolver != null) {
            evaluationContext.setBeanResolver(beanResolver);
        }
        return evaluationContext;
    }
}
